<template>
  <div class="dh-field">
    <div class="van-hairline--bottom">
      <van-field v-model="resultLabel" v-bind="$attrs" readonly :is-link="$attrs.disabled === undefined" error-message-align="right" input-align="right" @click="showPopu($attrs.disabled as any)" class="dh-cell" />
      <van-popup v-model:show="data.showPop" position="bottom" class="">
        <div class="van-picker__toolbar">
          <button type="button" class="van-picker__cancel" @click="cancel">取消</button>
          <div class="van-ellipsis van-picker__title">
            {{ $attrs.label }}<span v-if="max">(最多选{{ max }}个)</span>
          </div>
          <button type="button" class="van-picker__confirm" @click="onConfirm">确认</button>
        </div>
        <div class="checkbox-con" style="max-height: 264px; overflow-y: auto">
          <van-field v-model="data.searchVal" placeholder="搜索" @update:model-value="search" v-if="isSearch" input-align="left" />
          <van-cell title="全选" v-if="!max">
            <template #right-icon>
              <van-checkbox name="all" @click="toggleAll" v-model="data.checkedAll" />
            </template>
          </van-cell>
          <van-cell title="不包含" v-if="noIncludeOption">
            <template #right-icon>
              <van-checkbox name="00" @click="unToggleAll" v-model="data.unCheckedAll" />
            </template>
          </van-cell>

          <van-checkbox-group :max="max" v-model="data.checkboxValue" @change="change" ref="checkboxGroup">
            <van-cell-group>
              <van-cell v-for="(item, index) in data.columnsData" clickable :key="item[option.value]" :title="item[option.label]" @click="toggle(index, item)">
                <template #right-icon>
                  <van-checkbox :name="item[option.value]" ref="checkboxes" />
                </template>
              </van-cell>
            </van-cell-group>
          </van-checkbox-group>
        </div>
      </van-popup>
    </div>
  </div>
</template>

<script setup lang="ts">
import type { CheckboxGroupInstance } from 'vant'
//更新发送model
const emit = defineEmits(['update:modelValue', 'confirm', 'change', 'cancel', 'clickItem'])

const props = defineProps({
  modelValue: {
    type: Array<object | number | string>,
    default: false
  },
  columns: {
    type: Array<object | number | string>,
    default: function () {
      return []
    }
  },

  option: {
    type: Object,
    default: function () {
      return { label: 'name', value: 'code' }
    }
  },
  isSearch: {
    type: Boolean,
    default: false
  },
  max: {
    // 最大可选
    type: [Number, String],
    default: 0
  },
  noIncludeOption: {
    // 是否有不包含选项
    type: Boolean,
    default: false
  }
})
interface Config {
  searchVal: string
  columnsData: Array<any>
  checkboxValue: Array<any> //	所有选中项的标识符
  checkedAll: boolean
  resultValue: Array<any>
  showPop: boolean
  unCheckedAll: boolean
}

const data: Config = reactive({
  searchVal: '',
  columnsData: JSON.parse(JSON.stringify(props.columns)),
  checkboxValue: [],
  checkedAll: false,
  resultValue: [],
  showPop: false,
  unCheckedAll: false
})

//回显label
const resultLabel = computed(() => {
  let columns: any[] = JSON.parse(JSON.stringify(props.columns))
  if (props.noIncludeOption) {
    // 开启不包含
    let obj = {
      [props.option.label]: '不包含',
      [props.option.value]: '00'
    }
    columns.unshift(obj)
  }
  const res = columns.filter(item => {
    return data.resultValue?.indexOf(item[props.option.value]) > -1
  })
  const resLabel = res.map(item => {
    return item[props.option.label]
  })
  return resLabel.join(',')
})

const showPopu = (disabled: boolean | undefined = false) => {
  data.columnsData = JSON.parse(JSON.stringify(props.columns))
  if (disabled !== undefined && disabled !== false) {
    return false
  } else {
    data.showPop = !data.showPop
  }
}

//因为props的数据是只读，不能用于绑定model，所以需要重新定义赋值
watch(
  () => props.modelValue,
  newVal => {
    data.resultValue = newVal
    data.checkboxValue = JSON.parse(JSON.stringify(newVal))
  },
  {
    immediate: true,
    deep: true
  }
)

//搜索
const search = (val: string) => {
  if (val) {
    data.columnsData = data.columnsData.filter(item => {
      return item[props.option.label]?.indexOf(val) > -1
    })
  } else {
    data.columnsData = JSON.parse(JSON.stringify(props.columns))
  }
}

//获取选中值得完整数据
const getData = (val: any) => {
  const res: any = data.columnsData.filter(item => {
    return val.indexOf(item[props.option.value]) > -1
  })
  return res || ''
}
//操作事件
const onConfirm = () => {
  //确认
  data.resultValue = data.checkboxValue
  emit('confirm', data.resultValue, getData(data.resultValue))
}
const change = (val: any) => {
  //数据改变
  emit('change', val, getData(val))
}
const cancel = () => {
  //取消
  data.resultValue = []
  emit('cancel')
}
watch(
  () => data.resultValue,
  newVal => {
    //当结果确定后，重置数据
    data.searchVal = ''
    data.columnsData = JSON.parse(JSON.stringify(props.columns))
    data.showPop = false
    emit('update:modelValue', newVal)
  },
  {
    immediate: true,
    deep: true
  }
)

// 全选非全选
const checked = ref([])
const checkboxGroup = ref<CheckboxGroupInstance>()
const toggle = (index: number | string, item: any) => {
  data.unCheckedAll = false
  data.checkboxValue = data.checkboxValue.filter(item => item != '00')
  emit('clickItem', item) //单条数据点击
  checked?.value[index]?.toggle()
}
const toggleAll = () => {
  data.unCheckedAll = false
  data.checkboxValue = data.checkboxValue.filter(item => item != '00')
  checkboxGroup?.value?.toggleAll(data.checkedAll)
}
const unToggleAll = () => {
  // 不包含
  checkboxGroup?.value?.toggleAll(false)
  data.checkboxValue = ['00']
}
//全选非全选监听
watch(
  () => [data.columnsData, data.checkboxValue],
  newVal => {
    const columnsData = newVal[0]
    const checkboxValue = newVal[1]
    const reg = columnsData.length && columnsData.length === data.checkboxValue.length
    const reg2 = checkboxValue.length && checkboxValue.length === data.columnsData.length
    if (reg || reg2) {
      data.checkedAll = true
    } else {
      data.checkedAll = false
    }
  },
  {
    immediate: true,
    deep: true
  }
)

//这里需要暴露出去不然父组件调用不到这个方法
defineExpose({
  showPopu
})
</script>

<style lang="scss" scoped>
.dh-field {
  padding: 0 16px;
  background: #fff;
  .dh-cell.van-cell {
    padding: 10px 0;
  }
  .dh-cell.van-cell--required::before {
    left: -8px;
  }
  .van-popup {
    border-radius: 20px 20px 0 0;
  }
}
</style>
